package it.antonio.ilpizze.te;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Map;

public class Template {
	private Reader reader;
	private Lexer lexer;
	
	private boolean compiled = false;
	private RenderCommand command;
	private String templateText;
	
	public Map<String, Filter> filters = new HashMap<String, Filter>();
	
	
	public Template(String text) {
		this.reader = new CharArrayReader(text.toCharArray());
		this.lexer = new Lexer(this.reader);
	}
	public Template(InputStream stream) {
		this.reader = new StreamReader(stream);
		this.lexer = new Lexer(this.reader);
	}
	
	public void compile(){
		Tokens tokens = lexer.tokens();
		try{
			command = Parser.parse(tokens);
		} catch(ParseException e){
			throw e;
		} finally {
			reader.close();
			
			Token token = tokens.first();
			StringBuffer buffer = new StringBuffer();
			while(token != null) {
				buffer.append(token.asText());
				token = token.next;
			}
			templateText = buffer.toString();
			compiled = true;
			
			
			
		}
		
	}
	
	public String render(Map<String, Object> model){
		if(compiled == false) compile();
		
		StringBuffer buffer = new StringBuffer();
		command.contribute(model, filters, buffer);
		
		return buffer.toString();
	}
	
	@Override
	public String toString() {
		if(compiled == false) compile();
		return templateText;
	}
	
	public String errorText(ParseException e){
		int position = 0;
		StringBuffer buffer = new StringBuffer();
		BufferedReader reader = new BufferedReader(new StringReader(templateText));
		try {
			for(String line; (line = reader.readLine()) != null; ){
				position += line.length() + 1;
				
				if(position >= e.getPosition()){
					buffer.append(line + "\n");
					
					int errorPositionInLine = line.length() - (position - e.getPosition() - 1);
					for(int i = 0; i< errorPositionInLine; i++) buffer.append(" ");
					buffer.append("^");
					return e.getMessage() +"\n" + buffer.toString();
					
				}
				
			}
		} catch (IOException e1) {
			throw new IllegalStateException(e1);
		}
		
		throw new IllegalStateException("Illegal Parse Exception");
	}
	
}
